//////////////////////////////////////////////
// ImageBase.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkImages
{
	class Image ;
}

/// Includes ---------------------------------

// nkImages
#include "../Dll/DllDefines.h"

#include "../Enums/PixelFormat.h"

#include "AlignmentDescriptor.h"
#include "ImageDescriptor.h"

// nkMaths
#include <NilkinsMaths/Algebra/Vector.h>

// nkMemory
#include <NilkinsMemory/Containers/BufferCast.h>
#include <NilkinsMemory/Containers/BufferView.h>

/// Internals --------------------------------

template class DLL_IMAGES_EXPORT nkMemory::BufferCast<nkImages::ImageDescriptor> ;

/// Class ------------------------------------

namespace nkImages
{
	class DLL_IMAGES_EXPORT ImageBase
	{
		public :

			// Constructor, destructor
			ImageBase () noexcept ;
			ImageBase (unsigned int width, unsigned int height, unsigned int depth, PIXEL_FORMAT format, unsigned int pixelOrBlockByteSize = 0, unsigned int rowByteSize = 0, unsigned int sliceByteSize = 0) noexcept ;
			ImageBase (unsigned int width, unsigned int height, unsigned int depth, unsigned int arraySize, unsigned int mips, PIXEL_FORMAT format, unsigned int pixelOrBlockByteSize = 0) noexcept ;
			ImageBase (nkMemory::BufferCast<ImageDescriptor>&& images, PIXEL_FORMAT format, unsigned int pixelOrBlockByteSize, bool alphaPremultiplied = false, bool cubeMap = false) noexcept ;
			ImageBase (const ImageBase& other) noexcept ;
			ImageBase (ImageBase&& other) noexcept ;
			virtual ~ImageBase () ;

			// Getters
			unsigned int getWidth (unsigned int mip = 0u) const ;
			unsigned int getHeight (unsigned int mip = 0u) const ;
			unsigned int getDepthOrArraySize (unsigned int mip = 0u) const ;
			unsigned int getMipCount () const ;
			PIXEL_FORMAT getFormat () const ;
			unsigned int getPixelByteSize () const ;
			unsigned int getRowByteSize (unsigned int mip = 0u) const ;
			unsigned int getSliceByteSize (unsigned int mip = 0u) const ;
			bool getAlphaPremultiplied () const ;
			bool getCubeMap () const ;
			bool isArray () const ;

			// Setters
			void setFormat (PIXEL_FORMAT value) ;
			void setPixelOrBlockByteSize (unsigned int value) ;
			void setAlphaPremultiplied (bool value) ;
			void setCubeMap (bool value) ;

			// Utils
			nkMaths::Vector getPixel (unsigned int x, unsigned int y, unsigned int z = 0u, unsigned int mip = 0u) const ;
			void setPixel (nkMaths::Vector v, unsigned int x, unsigned int y, unsigned int z = 0u, unsigned int mip = 0u) ;
			Image decompress (const AlignmentDescriptor& alignmentDescriptor = AlignmentDescriptor()) const ;

			// Data accessors
			virtual unsigned char* getDataPtr () const = 0 ;
			virtual unsigned long long getDataByteSize () const = 0 ;
			virtual nkMemory::BufferView<> getDataBuffer () const = 0 ;
			virtual bool isView () const = 0 ;

			// Operators
			ImageBase& operator= (const ImageBase& other) noexcept ;
			ImageBase& operator= (ImageBase&& other) noexcept ;

		protected :

			// Attributes
			// Image characteristics for its slices and mips
			nkMemory::BufferCast<ImageDescriptor> _images ;
			PIXEL_FORMAT _format ;
			
			// Alignment in memory
			unsigned int _pixelOrBlockByteSize ;

			// Flags
			bool _alphaPremultiplied ;
			bool _cubeMap ;
	} ;
}